package com.heima.article.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.article.entity.ApArticle;
import com.heima.article.entity.ApAuthor;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.ApArticleContentService;
import com.heima.article.service.ApArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.service.ApAuthorService;
import com.heima.article.service.FreemarkerService;
import com.heima.common.util.BeanHelper;
import com.heima.common.util.JsonUtils;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.media.dtos.ArticleLoadDTO;
import com.heima.model.media.dtos.WmNewsResultDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 文章信息表，存储已发布的文章 服务实现类
 * </p>
 *
 * @author HM
 * @since 2023-05-25
 */
@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {

    @Autowired
    private ApAuthorService apAuthorService;
    @Autowired
    private ApArticleContentService contentService;
    @Autowired
    private FreemarkerService freemarkerService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * feign, 当自媒体文章审核通过以后，调用此方法保存文章，保存文章内容
     * @param dto
     * @return
     */
    @Override
    public Long createArticle(WmNewsResultDTO dto) {
        // 跟据自媒体文章的id查询article，有就更新，没有就插入
        // ap_article
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApArticle::getWmNewsId,dto.getId());
        ApArticle articleDB  = this.getOne(queryWrapper);
        Long articleId = 0L;
        if (articleDB == null){
            //insert
            LambdaQueryWrapper<ApAuthor> authorLambdaQueryWrapper = new LambdaQueryWrapper<>();
            authorLambdaQueryWrapper.eq(ApAuthor::getWmUserId,dto.getWmUserId());
            //根据wmUserId查询author数据
            ApAuthor apAuthorDB = apAuthorService.getOne(authorLambdaQueryWrapper);
            ApArticle articleInsert = BeanHelper.copyProperties(dto,ApArticle.class);
            articleInsert.setId(null);
            articleInsert.setAuthorId(apAuthorDB.getUserId());
            articleInsert.setAuthorName(apAuthorDB.getName());
            articleInsert.setLayout(dto.getType());
            articleInsert.setFlag(0);
            articleInsert.setLikes(0L);
            articleInsert.setComments(0L);
            articleInsert.setCollection(0L);
            articleInsert.setViews(0L);
            articleInsert.setCreatedTime(new Date());
            articleInsert.setIsComment(true);
            articleInsert.setIsForward(true);
            articleInsert.setIsDelete(false);
            articleInsert.setIsDown(false);
            articleInsert.setWmNewsId(dto.getId());
            this.save(articleInsert);
            articleId = articleInsert.getId();
        }else{
            // update
            ApArticle toBeUpdate =  BeanHelper.copyProperties(dto, ApArticle.class);
            toBeUpdate.setId(articleDB.getId());
            toBeUpdate.setLayout(dto.getType());
            this.updateById(toBeUpdate);
            articleId = articleDB.getId();
        }
        // ap_article_content
        contentService.saveContent(articleId, dto.getContent());
        // 异步 生成静态的html，上传minio，回填url地址到ap_article
        freemarkerService.asyncContentStatic(articleId, dto.getContent());
        return articleId;
    }

    /**
     * app首页显示文章数据
     * @param dto
     * @return
     */
    @Override
    public List<ApArticle> load(ArticleLoadDTO dto) {
        return loadmore(dto);
    }

    @Override
    public List<ApArticle> loadmore(ArticleLoadDTO dto) {
        // 如果是推荐频道，查询redis的zset
        if(dto.getChannelId() != null && dto.getChannelId() == 0){
            return loadHotArticles(dto);
        }
        // 比当前页，最小的还要小
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        // 默认的过滤条件
        queryWrapper.eq(ApArticle::getIsDown, false);
        queryWrapper.eq(ApArticle::getIsDelete, false);
        queryWrapper.lt(ApArticle::getPublishTime, dto.getMinTime());
        queryWrapper.eq(dto.getChannelId()!=null && dto.getChannelId()>0, ApArticle::getChannelId, dto.getChannelId());
        // 添加发布时间的排序
        queryWrapper.orderByDesc(ApArticle::getPublishTime);
        // limit ?
        Page<ApArticle> ipgae= new Page<>(1, dto.getSize());
        // 查询
        Page<ApArticle> pageResponse = this.page(ipgae, queryWrapper);
        return pageResponse.getRecords();
    }

    @Override
    public List<ApArticle> loadnew(ArticleLoadDTO dto) {
        // 如果是推荐频道，查询redis的zset
        if(dto.getChannelId() != null && dto.getChannelId() == 0){
            return loadHotArticles(dto);
        }
        // 比当前页最大的数据还要大
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApArticle::getIsDown, false);
        queryWrapper.eq(ApArticle::getIsDelete, false);
        queryWrapper.gt(ApArticle::getPublishTime, dto.getMaxTime());
        queryWrapper.eq(dto.getChannelId()!=null && dto.getChannelId()>0, ApArticle::getChannelId, dto.getChannelId());
        // 添加发布时间的排序
        queryWrapper.orderByDesc(ApArticle::getPublishTime);
        // limit ?
        Page<ApArticle> ipgae= new Page<>(1, dto.getSize());
        // 查询
        Page<ApArticle> pageResponse = this.page(ipgae, queryWrapper);
        return pageResponse.getRecords();
    }

    // TODO zset手机端的分页
    private List<ApArticle> loadHotArticles(ArticleLoadDTO dto) {
        Set<String> articleIds = redisTemplate.boundZSetOps(ApHotArticlesServiceImpl.PREFIX).reverseRangeByScore(0, Double.MAX_VALUE);
        if(CollectionUtils.isEmpty(articleIds)){
            return new ArrayList<>();
        }
        List<ApArticle> result = new ArrayList<>(articleIds.size());
        for(String articleId : articleIds){
            //TODO article上下架的时候，redis需要同步上下架
            String json = redisTemplate.boundValueOps(ApHotArticlesServiceImpl.PREFIX + ":" + articleId).get();
            if(!StringUtils.isEmpty(json)){
                ApArticle article = JsonUtils.toBean(json, ApArticle.class);
                result.add(article);
            }
        }
        return result;
    }

    /**
     * feign, 搜索服务做批量的数据导入
     * @param page
     * @param size
     * @return
     */
    @Override
    public List<ArticleDto> findByPage(int page, int size) {
        Page<ApArticle>  ipage = new Page<>(page, size);
        return this.baseMapper.findByPage(ipage);
    }

    @Override
    public ArticleDto findById(long articleId) {
        return this.baseMapper.findById(articleId);
    }

    @Override
    public List<ApArticle> findLatestArticlesIn(int days) {
        LocalDateTime startTime = LocalDate.now().minusDays(days).atStartOfDay();
        LambdaQueryWrapper<ApArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ApArticle::getIsDelete, false);
        queryWrapper.eq(ApArticle::getIsDown, false);
        //发布时间
        queryWrapper.ge(ApArticle::getPublishTime, startTime);
        return this.list(queryWrapper);
    }
}
